package com.bto.solar.work.aliyunsms;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson2.JSON;
import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.service.dysmsapi20170525.AsyncClient;
import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsResponseBody;
import com.bto.solar.work.common.BizException;
import com.bto.solar.work.common.RedisService;
import com.bto.solar.work.constant.Constants;
import com.bto.solar.work.constant.TokenConstants;
import com.bto.solar.work.dao.IUserService;
import com.bto.solar.work.entity.User;
import com.bto.solar.work.utils.NullUtils;
import darabonba.core.client.ClientOverrideConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class SmsService {

    @Value("${aliyun.sms.accesskey-id}")
    private String accessKeyId;
    @Value("${aliyun.sms.accessKey-secret}")
    private String accessKeySecret;
    @Value("${aliyun.sms.region-id}")
    private String regionId;
    @Value("${aliyun.sms.endpoint-override}")
    private String endpointOverride;
    @Value("${aliyun.sms.sign-name}")
    private String signName;

    @Autowired
    private IUserService userService;
    @Autowired
    private RedisService redisService;

    private StaticCredentialProvider getStaticCredentialProvider() {
        return StaticCredentialProvider.create(Credential.builder()
                .accessKeyId(accessKeyId)
                .accessKeySecret(accessKeySecret)
                .build());
    }

    private AsyncClient getAsyncClient() {
        return AsyncClient.builder()
                .region(regionId)
                .credentialsProvider(getStaticCredentialProvider())
                .overrideConfiguration(
                        ClientOverrideConfiguration.create()
                                .setEndpointOverride(endpointOverride)
                )
                .build();
    }

    private SendSmsRequest setSendSmsRequest(String phone, String code, String templateCode) {
        Map<String, String> map = new HashMap<>();
        map.put("code", code);
        code = JSON.toJSONString(map);
        return SendSmsRequest.builder()
                .phoneNumbers(phone)
                .signName(signName)
                .templateCode(templateCode)
                .templateParam(code)
                .build();
    }

    public SendSmsResponseBody sendAuthCode (String phone, String code) {
        try {
            SendSmsRequest sendSmsRequest = setSendSmsRequest(phone, code, Constants.TEMPLATE_AUTH_CODE);
            AsyncClient client = getAsyncClient();
            CompletableFuture<SendSmsResponse> response = client.sendSms(sendSmsRequest);
            SendSmsResponse resp = response.get();
            if (resp == null) {
                throw new BizException("手机号：{} 的登录用户的短信发送失败",
                        sendSmsRequest.getPhoneNumbers());
            } else if (!"OK".equals(resp.getBody().getCode())) {
                throw new BizException("手机号：{} 的登录用户的短信发送失败：{}",
                        sendSmsRequest.getPhoneNumbers(), resp.getBody().getMessage());
            }
            client.close();
            return resp.getBody();
        }catch (BizException e) {
            log.error(e.getMessage());
            throw new BizException(e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BizException("短信发送失败！请联系工作人员");
        }
    }

    public void getSmsCode (String phone, String type) {
        if(!Validator.isMobile(phone)){
            throw new BizException("获取失败，请稍后重试！");
        }
        User user = userService.lambdaQuery().eq(User::getPhone, phone).one();
        if(NullUtils.isNull(user)){
            throw new BizException("获取失败，请稍后重试！");
        }
        //生成6位数纯数字验证码
        String code = RandomUtil.randomNumbers(6);
        //发送短信
        sendAuthCode(phone, code);
        //保存code，有效期为5分钟
        if (Constants.LOGIN.equals(type)) {
            redisService.setCacheObject(TokenConstants.SMS_CODE_LOGIN_KEY + phone,
                    code, TokenConstants.SMS_EXPIRE_MIN , TimeUnit.MINUTES);
        } else if (Constants.PASSWORD.equals(type)) {
            redisService.setCacheObject(Constants.SMS_CODE_PASSWORD_KEY + phone,
                    code, TokenConstants.SMS_EXPIRE_MIN , TimeUnit.MINUTES);
        }


    }
}
